package com.guiji.file.controller;

import cn.hutool.core.util.HashUtil;
import com.guiji.common.annotation.Log;
import com.guiji.common.annotation.RepeatSubmit;
import com.guiji.common.core.controller.BaseController;
import com.guiji.common.core.domain.AjaxResult;
import com.guiji.common.enums.BusinessType;
import com.guiji.file.service.IResourceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;

/**
 * @ClassName UploadZipController
 * @Description TODO
 * @Author 钟维澎（四月）
 * @Date 2021/7/26 16:06
 * @Version 1.0
 */
@Api(value = "超大文件资源控制器", tags = {"超大文件资源管理"})
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@RestController
@RequestMapping("/file/zip")
public class UploadZipController extends BaseController {

	private final IResourceService iResourceService;

	@Value("${uploadFolder}")
	private String filePath;

	/**
	 * 文件资源上传
	 */
	@ApiOperation("新增文件资源")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "file", value = "文件", dataType = "java.io.File", required = true),
	})
	//@PreAuthorize("@ss.hasPermi('file:zip:add')")
	@Log(title = "文件资源", businessType = BusinessType.INSERT)
	//@RepeatSubmit
	@PostMapping("/add")
	public AjaxResult<Void> add(HttpServletRequest request, HttpServletResponse response, String guid, @NotNull Integer chunk, @RequestPart("file") MultipartFile file, Integer chunks){
		try {
			boolean isMultipart = ServletFileUpload.isMultipartContent(request);
			if (isMultipart) {
				// 临时目录用来存放所有分片文件
				String tempFileDir = filePath + HashUtil.javaDefaultHash(guid);
				File parentFileDir = new File(tempFileDir);
				if (!parentFileDir.exists()) {
					parentFileDir.mkdirs();
				}
				// 分片处理时，前台会多次调用上传接口，每次都会上传文件的一部分到后台
				File tempPartFile = new File(parentFileDir, guid + "_" + chunk + ".part");
				FileUtils.copyInputStreamToFile(file.getInputStream(), tempPartFile);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return AjaxResult.success();
	}


	/**
	 * 合并文件
	 *
	 * @param guid
	 * @param fileName
	 * @throws Exception
	 */
	@ApiOperation("合并文件资源")
	//@PreAuthorize("@ss.hasPermi('file:zip:merge')")
	@Log(title = "合并文件资源", businessType = BusinessType.INSERT)
	@RepeatSubmit
	@GetMapping("/merge")
	public AjaxResult<Void> mergeFile(String guid, String fileName) {
		// 得到 destTempFile 就是最终的文件
		try {
			File parentFileDir = new File(filePath + HashUtil.javaDefaultHash(guid));
			if (parentFileDir.isDirectory()) {
				File destTempFile = new File(filePath + "/merge", UUID.randomUUID() + fileName);
				if (!destTempFile.exists()) {
					//先得到文件的上级目录，并创建上级目录，在创建文件,
					destTempFile.getParentFile().mkdir();
					try {
						//创建文件
						destTempFile.createNewFile(); //上级目录没有创建，这里会报错
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				System.out.println(parentFileDir.listFiles().length);
				for (int i = 0; i < parentFileDir.listFiles().length; i++) {
					File partFile = new File(parentFileDir, guid + "_" + i + ".part");
					FileOutputStream destTempfos = new FileOutputStream(destTempFile, true);
					//遍历"所有分片文件"到"最终文件"中
					FileUtils.copyFile(partFile, destTempfos);
					destTempfos.close();
				}
				// 删除临时目录中的分片文件
				FileUtils.deleteDirectory(parentFileDir);
				return AjaxResult.success();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return AjaxResult.error();
		}
		return null;
	}
}
